home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / manageme / tcpdump-.001 / tcpdump-~ / tcpdump-3.0.2-linux / tcpdump-3.0.2 / print-ip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-15  |  8.2 KB  |  363 lines

  1. /*
  2.  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21.  
  22. #ifndef lint
  23. static char rcsid[] =
  24.     "@(#) $Header: print-ip.c,v 1.38 94/06/14 20:17:40 leres Exp $ (LBL)";
  25. #endif
  26.  
  27. #include <sys/param.h>
  28. #include <sys/time.h>
  29. #include <sys/types.h>
  30. #include <sys/socket.h>
  31.  
  32. #include <netinet/in.h>
  33. #include <netinet/in_systm.h>
  34. #include <netinet/ip.h>
  35. #include <netinet/ip_var.h>
  36. #include <netinet/udp.h>
  37. #include <netinet/udp_var.h>
  38. #include <netinet/tcp.h>
  39. #include <netinet/tcpip.h>
  40.  
  41. #include <stdio.h>
  42. #ifdef __STDC__
  43. #include <stdlib.h>
  44. #endif
  45. #include <unistd.h>
  46.  
  47. #include "interface.h"
  48. #include "addrtoname.h"
  49.  
  50. static void
  51. igmp_print(register const u_char *bp, register int len,
  52.        register const u_char *bp2)
  53. {
  54.     register const struct ip *ip;
  55.     register const u_char *ep;
  56.  
  57.     ip = (const struct ip *)bp2;
  58.     ep = (const u_char *)snapend;
  59.         (void)printf("%s > %s: ",
  60.         ipaddr_string(&ip->ip_src),
  61.         ipaddr_string(&ip->ip_dst));
  62.  
  63.     if (bp + 7 > ep) {
  64.         (void)printf("[|igmp]");
  65.         return;
  66.     }
  67.     switch (bp[0] & 0xf) {
  68.     case 1:
  69.         (void)printf("igmp query");
  70.         if (*(int *)&bp[4])
  71.             (void)printf(" [gaddr %s]", ipaddr_string(&bp[4]));
  72.         if (len != 8)
  73.             (void)printf(" [len %d]", len);
  74.         break;
  75.     case 2:
  76.         (void)printf("igmp report %s", ipaddr_string(&bp[4]));
  77.         if (len != 8)
  78.             (void)printf(" [len %d]", len);
  79.         break;
  80.     case 3:
  81.         (void)printf("igmp dvmrp %s", ipaddr_string(&bp[4]));
  82.         if (len < 8)
  83.             (void)printf(" [len %d]", len);
  84.         break;
  85.     default:
  86.         (void)printf("igmp-%d", bp[0] & 0xf);
  87.         break;
  88.     }
  89.     if ((bp[0] >> 4) != 1)
  90.         (void)printf(" [v%d]", bp[0] >> 4);
  91.     if (bp[1])
  92.         (void)printf(" [b1=0x%x]", bp[1]);
  93. }
  94.  
  95. /*
  96.  * print the recorded route in an IP RR, LSRR or SSRR option.
  97.  */
  98. static void
  99. ip_printroute(const char *type, register const u_char *cp, int length)
  100. {
  101.     int ptr = cp[2] - 1;
  102.     int len;
  103.  
  104.     printf(" %s{", type);
  105.     if ((length + 1) & 3)
  106.         printf(" [bad length %d]", length);
  107.     if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
  108.         printf(" [bad ptr %d]", cp[2]);
  109.  
  110.     type = "";
  111.     for (len = 3; len < length; len += 4) {
  112.         if (ptr == len)
  113.             type = "#";
  114. #ifdef TCPDUMP_ALIGN
  115.         {
  116.         struct in_addr addr;
  117.         bcopy((char *)&cp[len], (char *)&addr, sizeof(addr));
  118.         printf("%s%s", type, ipaddr_string(&addr));
  119.         }
  120. #else
  121.         printf("%s%s", type, ipaddr_string(&cp[len]));
  122. #endif
  123.         type = " ";
  124.     }
  125.     printf("%s}", ptr == len? "#" : "");
  126. }
  127.  
  128. /*
  129.  * print IP options.
  130.  */
  131. static void
  132. ip_optprint(register const u_char *cp, int length)
  133. {
  134.     int len;
  135.  
  136.     for (; length > 0; cp += len, length -= len) {
  137.         int tt = *cp;
  138.  
  139.         len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1];
  140.         if (&cp[1] >= snapend || cp + len > snapend) {
  141.             printf("[|ip]");
  142.             return;
  143.         }
  144.         switch (tt) {
  145.  
  146.         case IPOPT_EOL:
  147.             printf(" EOL");
  148.             if (length > 1)
  149.                 printf("-%d", length - 1);
  150.             return;
  151.  
  152.         case IPOPT_NOP:
  153.             printf(" NOP");
  154.             break;
  155.  
  156.         case IPOPT_TS:
  157.             printf(" TS{%d}", len);
  158.             break;
  159.  
  160.         case IPOPT_SECURITY:
  161.             printf(" SECURITY{%d}", len);
  162.             break;
  163.  
  164.         case IPOPT_RR:
  165.             printf(" RR{%d}=", len);
  166.             ip_printroute("RR", cp, len);
  167.             break;
  168.  
  169.         case IPOPT_SSRR:
  170.             ip_printroute("SSRR", cp, len);
  171.             break;
  172.  
  173.         case IPOPT_LSRR:
  174.             ip_printroute("LSRR", cp, len);
  175.             break;
  176.  
  177.         default:
  178.             printf(" IPOPT-%d{%d}", cp[0], len);
  179.             break;
  180.         }
  181.     }
  182. }
  183.  
  184. /*
  185.  * compute an IP header checksum.
  186.  * don't modifiy the packet.
  187.  */
  188. static int
  189. in_cksum(const struct ip *ip)
  190. {
  191.     register const u_short *sp = (u_short *)ip;
  192.     register u_int32 sum = 0;
  193.     register int count;
  194.  
  195.     /*
  196.      * No need for endian conversions.
  197.      */
  198.     for (count = ip->ip_hl * 2; --count >= 0; )
  199.         sum += *sp++;
  200.     while (sum > 0xffff)
  201.         sum = (sum & 0xffff) + (sum >> 16);
  202.     sum = ~sum & 0xffff;
  203.  
  204.     return (sum);
  205. }
  206.  
  207. /*
  208.  * print an IP datagram.
  209.  */
  210. void
  211. ip_print(register const u_char *bp, register int length)
  212. {
  213.     register const struct ip *ip;
  214.     register int hlen;
  215.     register int len;
  216.     register int off;
  217.     register const u_char *cp;
  218.  
  219.     ip = (const struct ip *)bp;
  220. #ifdef TCPDUMP_ALIGN
  221.     /*
  222.      * The IP header is not word aligned, so copy into abuf.
  223.      * This will never happen with BPF.  It does happen raw packet
  224.      * dumps from -r.
  225.      */
  226.     if ((int)ip & (sizeof(long)-1)) {
  227.         static u_char *abuf;
  228.  
  229.         if (abuf == 0)
  230.             abuf = (u_char *)malloc(snaplen);
  231.         bcopy((char *)ip, (char *)abuf, min(length, snaplen));
  232.         snapend += abuf - (u_char *)ip;
  233.         packetp = abuf;
  234.         ip = (struct ip *)abuf;
  235.     }
  236. #endif
  237.     if ((u_char *)(ip + 1) > snapend) {
  238.         printf("[|ip]");
  239.         return;
  240.     }
  241.     if (length < sizeof (struct ip)) {
  242.         (void)printf("truncated-ip %d", length);
  243.         return;
  244.     }
  245.     hlen = ip->ip_hl * 4;
  246.  
  247.     len = ntohs(ip->ip_len);
  248.     if (length < len)
  249.         (void)printf("truncated-ip - %d bytes missing!",
  250.             len - length);
  251.     len -= hlen;
  252.  
  253.     /*
  254.      * If this is fragment zero, hand it to the next higher
  255.      * level protocol.
  256.      */
  257.     off = ntohs(ip->ip_off);
  258.     if ((off & 0x1fff) == 0) {
  259.         cp = (const u_char *)ip + hlen;
  260.         switch (ip->ip_p) {
  261.  
  262.         case IPPROTO_TCP:
  263.             tcp_print(cp, len, (const u_char *)ip);
  264.             break;
  265.         case IPPROTO_UDP:
  266.             udp_print(cp, len, (const u_char *)ip);
  267.             break;
  268.         case IPPROTO_ICMP:
  269.             icmp_print(cp, (const u_char *)ip);
  270.             break;
  271.         case IPPROTO_ND:
  272.             (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
  273.                 ipaddr_string(&ip->ip_dst));
  274.             (void)printf(" nd %d", len);
  275.             break;
  276.         case IPPROTO_EGP:
  277.             egp_print(cp, len, (const u_char *)ip);
  278.             break;
  279. #ifndef IPPROTO_OSPF
  280. #define IPPROTO_OSPF 89
  281. #endif
  282.         case IPPROTO_OSPF:
  283.             ospf_print(cp, len, (const u_char *)ip);
  284.             break;
  285. #ifndef IPPROTO_IGMP
  286. #define IPPROTO_IGMP 2
  287. #endif
  288.         case IPPROTO_IGMP:
  289.             igmp_print(cp, len, (const u_char *)ip);
  290.             break;
  291. #ifndef IPPROTO_ENCAP
  292. #define IPPROTO_ENCAP 4
  293. #endif
  294.         case IPPROTO_ENCAP:
  295.             /* ip-in-ip encapsulation */
  296.             if (vflag)
  297.                 (void)printf("%s > %s: ",
  298.                          ipaddr_string(&ip->ip_src),
  299.                          ipaddr_string(&ip->ip_dst));
  300.             ip_print(cp, len);
  301.             if (! vflag) {
  302.                 printf(" (encap)");
  303.                 return;
  304.             }
  305.             break;
  306.         default:
  307.             (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
  308.                 ipaddr_string(&ip->ip_dst));
  309.             (void)printf(" ip-proto-%d %d", ip->ip_p, len);
  310.             break;
  311.         }
  312.     }
  313.     /*
  314.      * for fragmented datagrams, print id:size@offset.  On all
  315.      * but the last stick a "+".  For unfragmented datagrams, note
  316.      * the don't fragment flag.
  317.      */
  318.     if (off & 0x3fff) {
  319.         /*
  320.          * if this isn't the first frag, we're missing the
  321.          * next level protocol header.  print the ip addr.
  322.          */
  323.         if (off & 0x1fff)
  324.             (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
  325.                       ipaddr_string(&ip->ip_dst));
  326.         (void)printf(" (frag %d:%d@%d%s)", ntohs(ip->ip_id), len,
  327.             (off & 0x1fff) * 8,
  328.             (off & IP_MF)? "+" : "");
  329.     } else if (off & IP_DF)
  330.         (void)printf(" (DF)");
  331.  
  332.     if (ip->ip_tos)
  333.         (void)printf(" [tos 0x%x]", (int)ip->ip_tos);
  334.     if (ip->ip_ttl <= 1)
  335.         (void)printf(" [ttl %d]", (int)ip->ip_ttl);
  336.  
  337.     if (vflag) {
  338.         int sum;
  339.         char *sep = "";
  340.  
  341.         printf(" (");
  342.         if (ip->ip_ttl > 1) {
  343.             (void)printf("%sttl %d", sep, (int)ip->ip_ttl);
  344.             sep = ", ";
  345.         }
  346.         if ((off & 0x3fff) == 0) {
  347.             (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id));
  348.             sep = ", ";
  349.         }
  350.         sum = in_cksum(ip);
  351.         if (sum != 0) {
  352.             (void)printf("%sbad cksum %x!", sep,
  353.                      ntohs(ip->ip_sum));
  354.             sep = ", ";
  355.         }
  356.         if ((hlen -= sizeof(struct ip)) > 0) {
  357.             (void)printf("%soptlen=%d", sep, hlen);
  358.             ip_optprint((u_char *)(ip + 1), hlen);
  359.         }
  360.         printf(")");
  361.     }
  362. }
  363.